using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using FilteredStatistics.Data;
using ZoneFiveSoftware.Common.Visuals;
using ZoneFiveSoftware.Common.Data.Fitness;
using ZoneFiveSoftware.Common.Data.Measurement;
using FilteredStatistics.Common;
using FilteredStatistics.Controller;

namespace FilteredStatistics.View
{
    partial class PostProcessFilterSetupDialog : Form
    {
        public PostProcessFilterSetupDialog() :
            this(null)
        {
        }

        public PostProcessFilterSetupDialog(IActivity activity)
        {
            InitializeComponent();

            m_Activity = activity;

            // Setup localized text
            this.Text = PluginView.GetLocalizedString("PostProcessFilterSetupDialogText");
            MergeNearDistancesCheckBox.Text = PluginView.GetLocalizedString("MergeNearSectionsCheckBoxText");
            MergeNearTimesCheckBox.Text = PluginView.GetLocalizedString("MergeNearSectionsCheckBoxText");
            RemoveSmallDistancesCheckBox.Text = PluginView.GetLocalizedString("RemoveSmallSectionsCheckBoxText");
            RemoveSmallTimesCheckBox.Text = PluginView.GetLocalizedString("RemoveSmallSectionsCheckBoxText");
            RemoveMinimumAscentCheckBox.Text = PluginView.GetLocalizedString("RemoveSectionsThatHaveBetweenText");
            AndLabel.Text = PluginView.GetLocalizedString("AndText");
            OfAscentLabel.Text = PluginView.GetLocalizedString("OfAscentLabelText");
            RemoveMinimumDescentCheckBox.Text = PluginView.GetLocalizedString("RemoveSectionsThatHaveBetweenText");
            AndLabel2.Text = PluginView.GetLocalizedString("AndText");
            OfDescentLabel.Text = PluginView.GetLocalizedString("OfDescentLabelText");
            OKButton.Text = CommonResources.Text.ActionOk;
            Cancel_Button.Text = CommonResources.Text.ActionCancel;

            // Set default values
            MergeNearDistancesTextBox.Text = String.Format("{0:0.0}", 50);
            MergeNearTimesUpDown.Duration = 60;
            RemoveSmallDistancesTextBox.Text = String.Format("{0:0.0}", 50);
            RemoveSmallTimesUpDown.Duration = 60;
            RemoveMinimumAscentMinimumTextBox.Text = String.Format("{0:0.0}", 0);
            RemoveMinimumAscentMaximumTextBox.Text = String.Format("{0:0.0}", 50);
            RemoveMinimumDescentMinimumTextBox.Text = String.Format("{0:0.0}", 0);
            RemoveMinimumDescentMaximumTextBox.Text = String.Format("{0:0.0}", 50);

            // Fill in combo boxes
            MergeNearDistancesUnitComboBox.Items.Add(Length.Units.Meter);
            MergeNearDistancesUnitComboBox.Items.Add(Length.Units.Kilometer);
            MergeNearDistancesUnitComboBox.Items.Add(Length.Units.Yard);
            MergeNearDistancesUnitComboBox.Items.Add(Length.Units.Mile);
            if(activity != null)
            {
                MergeNearDistancesUnitComboBox.SelectedItem = Utils.MinorLengthUnit(activity.Category.DistanceUnits);
            }
            else
            {
                MergeNearDistancesUnitComboBox.SelectedItem = Utils.MinorLengthUnit(PluginMain.GetApplication().SystemPreferences.DistanceUnits);
            }
            MergeNearDistancesUnitComboBox.Format += new ListControlConvertEventHandler(DistanceUnitComboBox_Format);

            RemoveSmallDistancesUnitComboBox.Items.Add(Length.Units.Meter);
            RemoveSmallDistancesUnitComboBox.Items.Add(Length.Units.Kilometer);
            RemoveSmallDistancesUnitComboBox.Items.Add(Length.Units.Yard);
            RemoveSmallDistancesUnitComboBox.Items.Add(Length.Units.Mile);
            if (activity != null)
            {
                RemoveSmallDistancesUnitComboBox.SelectedItem = Utils.MinorLengthUnit(activity.Category.DistanceUnits);
            }
            else
            {
                RemoveSmallDistancesUnitComboBox.SelectedItem = Utils.MinorLengthUnit(PluginMain.GetApplication().SystemPreferences.DistanceUnits);
            }
            RemoveSmallDistancesUnitComboBox.Format += new ListControlConvertEventHandler(DistanceUnitComboBox_Format);

            RemoveMinimumAscentUnitComboBox.Items.Add(Length.Units.Meter);
            RemoveMinimumAscentUnitComboBox.Items.Add(Length.Units.Foot);
            if (activity != null)
            {
                RemoveMinimumAscentUnitComboBox.SelectedItem = Utils.MinorElevationUnit(activity.Category.ElevationUnits);
            }
            else
            {
                RemoveMinimumAscentUnitComboBox.SelectedItem = Utils.MinorElevationUnit(PluginMain.GetApplication().SystemPreferences.ElevationUnits);
            }
            RemoveMinimumAscentUnitComboBox.Format += new ListControlConvertEventHandler(DistanceUnitComboBox_Format);

            RemoveMinimumDescentUnitComboBox.Items.Add(Length.Units.Meter);
            RemoveMinimumDescentUnitComboBox.Items.Add(Length.Units.Foot);
            if (activity != null)
            {
                RemoveMinimumDescentUnitComboBox.SelectedItem = Utils.MinorElevationUnit(activity.Category.ElevationUnits);
            }
            else
            {
                RemoveMinimumDescentUnitComboBox.SelectedItem = Utils.MinorElevationUnit(PluginMain.GetApplication().SystemPreferences.ElevationUnits);
            }
            RemoveMinimumDescentUnitComboBox.Format += new ListControlConvertEventHandler(DistanceUnitComboBox_Format);

            // Disable all
            MergeNearDistancesTextBox.Enabled = false;
            MergeNearDistancesUnitComboBox.Enabled = false;
            MergeNearTimesUpDown.Enabled = false;
            RemoveSmallDistancesTextBox.Enabled = false;
            RemoveSmallDistancesUnitComboBox.Enabled = false;
            RemoveSmallTimesUpDown.Enabled = false;
            RemoveMinimumAscentMinimumTextBox.Enabled = false;
            RemoveMinimumAscentMaximumTextBox.Enabled = false;
            RemoveMinimumAscentUnitComboBox.Enabled = false;
            RemoveMinimumDescentMinimumTextBox.Enabled = false;
            RemoveMinimumDescentMaximumTextBox.Enabled = false;
            RemoveMinimumDescentUnitComboBox.Enabled = false;
        }

#region UI callbacks

        private void OKButton_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
            Close();
        }

        private void Cancel_Button_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
            Close();
        }
        
        void DistanceUnitComboBox_Format(object sender, ListControlConvertEventArgs e)
        {
            Length.Units item = (Length.Units)e.ListItem;

            e.Value = Length.LabelAbbr(item);
        }

        private void MergeNearDistanceCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            MergeNearDistancesTextBox.Enabled = MergeNearDistancesCheckBox.Checked;
            MergeNearDistancesUnitComboBox.Enabled = MergeNearDistancesCheckBox.Checked;
        }

        private void MergeNearTimeCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            MergeNearTimesUpDown.Enabled = MergeNearTimesCheckBox.Checked;
        }

        private void MergeNearDistancesTextBox_Validating(object sender, CancelEventArgs e)
        {
            float distanceEntered;

            if (!float.TryParse(MergeNearDistancesTextBox.Text, out distanceEntered) || distanceEntered < 0)
            {
                MessageBox.Show(PluginView.GetLocalizedString("InvalidDistanceEnteredText"),
                                PluginView.GetLocalizedString("ErrorText"),
                                MessageBoxButtons.OK, MessageBoxIcon.Error);

                e.Cancel = true;
            }
        }

        private void RemoveSmallDistancesCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            RemoveSmallDistancesTextBox.Enabled = RemoveSmallDistancesCheckBox.Checked;
            RemoveSmallDistancesUnitComboBox.Enabled = RemoveSmallDistancesCheckBox.Checked;
        }

        private void RemoveSmallTimesCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            RemoveSmallTimesUpDown.Enabled = RemoveSmallTimesCheckBox.Checked;
        }

        private void RemoveSmallDistancesTextBox_Validating(object sender, CancelEventArgs e)
        {
            float distanceEntered;

            if (!float.TryParse(RemoveSmallDistancesTextBox.Text, out distanceEntered) || distanceEntered < 0)
            {
                MessageBox.Show(PluginView.GetLocalizedString("InvalidDistanceEnteredText"),
                                PluginView.GetLocalizedString("ErrorText"),
                                MessageBoxButtons.OK, MessageBoxIcon.Error);

                e.Cancel = true;
            }
        }

        private void RemoveMinimumAscentCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            RemoveMinimumAscentMinimumTextBox.Enabled = RemoveMinimumAscentCheckBox.Checked;
            RemoveMinimumAscentMaximumTextBox.Enabled = RemoveMinimumAscentCheckBox.Checked;
            RemoveMinimumAscentUnitComboBox.Enabled = RemoveMinimumAscentCheckBox.Checked;
        }

        private void RemoveMinimumAscentMinimumTextBox_Validating(object sender, CancelEventArgs e)
        {
            float distanceEntered;

            if (!float.TryParse(RemoveMinimumAscentMinimumTextBox.Text, out distanceEntered) || distanceEntered < 0)
            {
                MessageBox.Show(PluginView.GetLocalizedString("InvalidDistanceEnteredText"),
                                PluginView.GetLocalizedString("ErrorText"),
                                MessageBoxButtons.OK, MessageBoxIcon.Error);

                e.Cancel = true;
            }
        }

        private void RemoveMinimumAscentMaximumTextBox_Validating(object sender, CancelEventArgs e)
        {
            float distanceEntered;

            if (!float.TryParse(RemoveMinimumAscentMaximumTextBox.Text, out distanceEntered) || distanceEntered < 0)
            {
                MessageBox.Show(PluginView.GetLocalizedString("InvalidDistanceEnteredText"),
                                PluginView.GetLocalizedString("ErrorText"),
                                MessageBoxButtons.OK, MessageBoxIcon.Error);

                e.Cancel = true;
            }
        }

        private void RemoveMinimumDescentCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            RemoveMinimumDescentMinimumTextBox.Enabled = RemoveMinimumDescentCheckBox.Checked;
            RemoveMinimumDescentMaximumTextBox.Enabled = RemoveMinimumDescentCheckBox.Checked;
            RemoveMinimumDescentUnitComboBox.Enabled = RemoveMinimumDescentCheckBox.Checked;
        }

        private void RemoveMinimumDescentMinimumTextBox_Validating(object sender, CancelEventArgs e)
        {
            float distanceEntered;

            if (!float.TryParse(RemoveMinimumDescentMinimumTextBox.Text, out distanceEntered) || distanceEntered < 0)
            {
                MessageBox.Show(PluginView.GetLocalizedString("InvalidDistanceEnteredText"),
                                PluginView.GetLocalizedString("ErrorText"),
                                MessageBoxButtons.OK, MessageBoxIcon.Error);

                e.Cancel = true;
            }
        }

        private void RemoveMinimumDescentMaximumTextBox_Validating(object sender, CancelEventArgs e)
        {
            float distanceEntered;

            if (!float.TryParse(RemoveMinimumDescentMaximumTextBox.Text, out distanceEntered) || distanceEntered < 0)
            {
                MessageBox.Show(PluginView.GetLocalizedString("InvalidDistanceEnteredText"),
                                PluginView.GetLocalizedString("ErrorText"),
                                MessageBoxButtons.OK, MessageBoxIcon.Error);

                e.Cancel = true;
            }
        }

#endregion

        public IFilterCriteria ConfiguredCriteria
        {
            get
            {
                List<IPostProcessFilter> filters = new List<IPostProcessFilter>();

                if (MergeNearDistancesCheckBox.Checked)
                {
                    filters.Add(new MergeNearDistancesPostProcessFilter(float.Parse(MergeNearDistancesTextBox.Text),
                                                                       (Length.Units)MergeNearDistancesUnitComboBox.SelectedItem));
                }

                if (MergeNearTimesCheckBox.Checked)
                {
                    filters.Add(new MergeNearTimesPostProcessFilter(new TimeSpan(0, 0, MergeNearTimesUpDown.Duration)));
                }

                if(RemoveSmallDistancesCheckBox.Checked)
                {
                    filters.Add(new RemoveSmallDistancesPostProcessFilter(float.Parse(RemoveSmallDistancesTextBox.Text),
                                                                         (Length.Units)RemoveSmallDistancesUnitComboBox.SelectedItem));
                }

                if (RemoveSmallTimesCheckBox.Checked)
                {
                    filters.Add(new RemoveSmallTimesPostProcessFilter(new TimeSpan(0, 0, RemoveSmallTimesUpDown.Duration)));
                }

                if (RemoveMinimumAscentCheckBox.Checked)
                {
                    filters.Add(new RemoveAscentRangeSectionsPostProcessFilter(float.Parse(RemoveMinimumAscentMinimumTextBox.Text),
                                                                               float.Parse(RemoveMinimumAscentMaximumTextBox.Text),
                                                                               (Length.Units)RemoveMinimumAscentUnitComboBox.SelectedItem));
                }

                if (RemoveMinimumDescentCheckBox.Checked)
                {
                    filters.Add(new RemoveDescentRangeSectionsPostProcessFilter(float.Parse(RemoveMinimumDescentMinimumTextBox.Text),
                                                                                float.Parse(RemoveMinimumDescentMaximumTextBox.Text),
                                                                                (Length.Units)RemoveMinimumDescentUnitComboBox.SelectedItem));
                }

                return new PostProcessFilterCriteria(filters);
            }
            set
            {
                if(value is PostProcessFilterCriteria)
                {
                    PostProcessFilterCriteria criteria = value as PostProcessFilterCriteria;

                    foreach (PostProcessNamedZone namedZone in criteria.NamedZones)
                    {
                        if (namedZone.PostProcessFilter is MergeNearDistancesPostProcessFilter)
                        {
                            MergeNearDistancesPostProcessFilter filter = namedZone.PostProcessFilter as MergeNearDistancesPostProcessFilter;

                            MergeNearDistancesCheckBox.Checked = true;
                            MergeNearDistancesTextBox.Text = filter.MaxGapDistance.ToString();
                            MergeNearDistancesUnitComboBox.SelectedItem = filter.DistanceUnit;
                        }
                        else if (namedZone.PostProcessFilter is MergeNearTimesPostProcessFilter)
                        {
                            MergeNearTimesPostProcessFilter filter = namedZone.PostProcessFilter as MergeNearTimesPostProcessFilter;

                            MergeNearTimesCheckBox.Checked = true;
                            MergeNearTimesUpDown.Duration = (UInt16)filter.MaxGapTime.TotalSeconds;
                        }
                        else if (namedZone.PostProcessFilter is RemoveSmallDistancesPostProcessFilter)
                        {
                            RemoveSmallDistancesPostProcessFilter filter = namedZone.PostProcessFilter as RemoveSmallDistancesPostProcessFilter;

                            RemoveSmallDistancesCheckBox.Checked = true;
                            RemoveSmallDistancesTextBox.Text = filter.MinDistance.ToString();
                            RemoveSmallDistancesUnitComboBox.SelectedItem = filter.DistanceUnit;
                        }
                        else if (namedZone.PostProcessFilter is RemoveSmallTimesPostProcessFilter)
                        {
                            RemoveSmallTimesPostProcessFilter filter = namedZone.PostProcessFilter as RemoveSmallTimesPostProcessFilter;

                            RemoveSmallTimesCheckBox.Checked = true;
                            RemoveSmallTimesUpDown.Duration = (UInt16)filter.MinTime.TotalSeconds;
                        }
                        else if (namedZone.PostProcessFilter is RemoveAscentRangeSectionsPostProcessFilter)
                        {
                            RemoveAscentRangeSectionsPostProcessFilter filter = namedZone.PostProcessFilter as RemoveAscentRangeSectionsPostProcessFilter;

                            RemoveMinimumAscentCheckBox.Checked = true;
                            RemoveMinimumAscentMinimumTextBox.Text = filter.RangeMinAscent.ToString();
                            RemoveMinimumAscentMaximumTextBox.Text = filter.RangeMaxAscent.ToString();
                            RemoveMinimumAscentUnitComboBox.SelectedItem = filter.ElevationUnit;
                        }
                        else if (namedZone.PostProcessFilter is RemoveDescentRangeSectionsPostProcessFilter)
                        {
                            RemoveDescentRangeSectionsPostProcessFilter filter = namedZone.PostProcessFilter as RemoveDescentRangeSectionsPostProcessFilter;

                            RemoveMinimumDescentCheckBox.Checked = true;
                            RemoveMinimumDescentMinimumTextBox.Text = filter.RangeMinDescent.ToString();
                            RemoveMinimumDescentMaximumTextBox.Text = filter.RangeMaxDescent.ToString();
                            RemoveMinimumDescentUnitComboBox.SelectedItem = filter.ElevationUnit;
                        }
                    }
                }
            }
        }

        private IActivity m_Activity = null;
    }
}